package com.acme.bankapp.service.bank;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.acme.bankapp.domain.bank.AbstractAccount;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.CheckingAccount;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.domain.bank.ClientExistsException;
import com.acme.bankapp.domain.bank.Gender;
import com.acme.bankapp.domain.bank.SavingAccount;

/**
 * Load bank data from feed file. For simplicity it doesn't handle IO exceptions
 * @author Artem Nikitin
 *
 */
public class BankDataLoaderService {
	
	private static final String ATTR_ACCOUNT_TYPE = "account_type";
	private static final String ATTR_BALANCE = "balance";
	private static final String ATTR_OVERDRAFT = "overdraft";
	private static final String ATTR_CLIENT_NAME = "cname";
	private static final String ATTR_CLIENT_GENDER = "cgender";
	private static final String GENDER_MALE = "gender.m";
	private static final String GENDER_FEMALE = "gender.f";
	private static final String ACCOUNT_TYPE_SAVING = "at.saving";
	private static final String ACCOUNT_TYPE_CHECKING = "at.checking";
	
	public Bank loadBank(File source) {
		Bank bank = new Bank();
		try (BufferedReader br = new BufferedReader(new FileReader(source))) {
			String serializedObject;
			while ((serializedObject = br.readLine()) != null) {
				try {
					loadClient(bank, serializedObject);
				} catch (ClientExistsException e) {
					e.printStackTrace();
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bank;
	}
	
	private void loadClient(Bank bank, String serializedClient) throws ClientExistsException {
		BankService bankService = new BankService();
		String[] attributes = serializedClient.split(";");
		Map<String, String> attributesMap = new HashMap<>();
		for (String attr : attributes) {
			String[] attrPair = attr.split("=");
			attributesMap.put(attrPair[0], attrPair[1]);
		}
		AbstractAccount account = createAccount(attributesMap);
		Client client = createClient(attributesMap);
		bankService.addAccount(client, account);
		bankService.addClient(bank, client);
	}

	private Client createClient(Map<String, String> attributes) {
		return new Client(attributes.get(ATTR_CLIENT_NAME), parseGender(attributes.get(ATTR_CLIENT_GENDER)));
	}

	private Gender parseGender(String gender) {
		switch (gender) {
		case GENDER_MALE:
			return Gender.MALE;
		case GENDER_FEMALE:
			return Gender.FEMALE;
		default:
			return null;
		}
	}

	private AbstractAccount createAccount(Map<String, String> attributes) {
		switch (attributes.get(ATTR_ACCOUNT_TYPE)) {
		case ACCOUNT_TYPE_SAVING:
			return new SavingAccount(Double.parseDouble(attributes.get(ATTR_BALANCE)));
		case ACCOUNT_TYPE_CHECKING:
			CheckingAccount account = new CheckingAccount(Double.parseDouble(attributes.get(ATTR_BALANCE)));
			account.setOverdraftLimit(Double.parseDouble(attributes.get(ATTR_OVERDRAFT)));
			return account;
		default:
			return null;
		}	
	}
	
}
